package com.sojson.constant;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Set;

import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.ObjectName;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;

import com.sojson.util.MavenUtil;
import com.sojson.util.StringUtil;
import com.sojson.util.file.enums.EPackageType;
import com.sojson.util.servlet.ServletUtil;
import com.sojson.util.text.Convert;

import lombok.extern.slf4j.Slf4j;

/**
 * 项目路径静态属性类
 * 
 * @author liu
 * @date 2020-09-09
 */
@Slf4j
public class IpConfig {

    /** 协议 */
    public static String agreement =
        Convert.toStr(Constant.PROPERTIES.getProperty("so.controller.mapping.agreement"), "http://");
    /** 公网路径 */
    public static String domain = Convert.toStr(Constant.PROPERTIES.getProperty("so.controller.mapping.domain"), null);
    /** 公网IP地址 */
    public static String addressPublic;
    /** 局域网IP地址 */
    public static String addressPrivate;
    /** 端口号 */
    public static int serverPort = Convert.toInt(Constant.PROPERTIES.getProperty("so.server.port"), 8080);
    /** 上下文路径是否存在 */
    public static boolean contextPathIsExist;
    /** 上下文路径 */
    public static String contextPath;
    /** 上下文路径的长度 */
    public static int contextPathLength;
    /** 项目全路径 */
    public static String url;

    static {
        // 初始化局域网IP
        IpConfig.addressPrivate = getHostAddress();

        // 初始化公网IP
        String msg = "公网IP获取失败,将把局域网IP: " + IpConfig.addressPrivate + "作为公网IP!!!";
        try {
            // 打开连接
            Document doc = Jsoup.connect("http://chaipip.com/").get();
            Elements eles = doc.select("#ip");
            addressPublic = eles.attr("value");
            if (isBlankString(addressPublic)) {
                log.error(msg);
                log.error(msg);
                log.error(msg);
                addressPublic = addressPrivate;
            } else {
                log.info("当前项目的公网IP为: " + IpConfig.addressPublic);
            }
        } catch (IOException e) {
            log.error(msg);
            log.error(msg);
            log.error(msg);
            log.error(e.getMessage());
        }

        // 初始化端口号
        Integer portByMbean = getPortByMbean();
        if (isNotBlankObject(portByMbean)) {
            IpConfig.serverPort = portByMbean;
        }

        // 初始化项目名称
        if (MavenUtil.PACKAGE_TYPE == EPackageType.JAR) {
            contextPath = Constant.PROPERTIES.getProperty("server.servlet.context-path");
            if (contextPath == null || contextPath.length() == 1) {
                contextPath = "";
            }
        } else if (MavenUtil.PACKAGE_TYPE == EPackageType.WAR) {
            String finalName = MavenUtil.getFinalName();
            if (MavenUtil.ROOT.equals(finalName)) {
                contextPath = "";
            } else {
                contextPath = "/" + finalName;
            }
        }
        contextPathIsExist = !"".equals(contextPath);
        contextPathLength = contextPath.length();

        // 初始化域名
        if (isBlankObject(domain)) {
            IpConfig.domain =
                new StringBuilder(IpConfig.addressPrivate).append(":").append(IpConfig.serverPort).toString();
        }

        // 初始化项目全路径
        IpConfig.url =
            new StringBuilder(IpConfig.agreement).append(IpConfig.domain).append(IpConfig.contextPath).toString();

        log.info("当前项目的全路径为: " + IpConfig.url);
    }

    /**
    * 获取本机ip
    * @return
    */
    public static String getHostAddress() {
        String hostAddress = null;
        try {
            hostAddress = ServletUtil.getLocalHostIp();
        } catch (Exception e) {
            return null;
        }
        return hostAddress;
    }

    /**
     * 获取当前Tomcat实例的端口
     *
     * @return
     * @throws Exception 
     */
    public static Integer getPortByMbean() {
        Integer portStr = null;
        MBeanServer mBeanServer = null;
        Set<ObjectName> objectNames = null;

        try {
            ArrayList<MBeanServer> mBeanServers = MBeanServerFactory.findMBeanServer(null);
            if (mBeanServers.size() > 0) {
                mBeanServer = mBeanServers.get(0);
            }
            if (mBeanServer == null) {
                // 没有发现JVM中关联的MBeanServer.
                return null;
            }

            objectNames = mBeanServer.queryNames(new ObjectName("Catalina:type=Connector,*"), null);
            if (objectNames == null || objectNames.size() <= 0) {
                // throw new Exception("没有发现JVM中关联的MBeanServer : " + mBeanServer.getDefaultDomain() + " 中的对象名称.");
                return null;
            }

            for (ObjectName objectName : objectNames) {
                String protocol = (String)mBeanServer.getAttribute(objectName, "protocol");
                if ("HTTP/1.1".equals(protocol)) {
                    portStr = isNotBlankObject(mBeanServer.getAttribute(objectName, "port"))
                        ? (Integer)mBeanServer.getAttribute(objectName, "port") : portStr;
                    break;
                }
            }
        } catch (Exception e) {
            return null;
        }
        // System.out.println("当前tomcat容器端口>>>" + portStr);
        return portStr;
    }

    /**
     * 判断一个字符串是否是空(空对象和空字符串和值为"null")
     * 
     * @param obj
     * @return
     */
    private static boolean isBlankString(String str) {
        return StringUtil.isBlankString(str);
    }

    /**
     * 判断一个对象是否是空(空对象)
     * 
     * @param obj
     * @return
     */
    private static boolean isBlankObject(Object obj) {
        return StringUtil.isBlankObject(obj);
    }

    /**
     * 判断一个对象是否不是空(空对象)
     * 
     * @param obj
     * @return
     */
    private static boolean isNotBlankObject(Object obj) {
        return StringUtil.isNotBlankObject(obj);
    }

}